package com.example.warehouse.sys.controller;

import com.example.warehouse.common.consts.HttpConsts;
import com.example.warehouse.common.ex.ServiceException;
import com.example.warehouse.common.pojo.vo.PageData;
import com.example.warehouse.common.web.JsonResult;
import com.example.warehouse.common.web.ServiceCode;
import com.example.warehouse.core.excel.ExcelUtil;
import com.example.warehouse.sys.pojo.entity.SysUser;
import com.example.warehouse.sys.pojo.param.AddNewUserParam;
import com.example.warehouse.sys.pojo.param.SysUserStandardParam;
import com.example.warehouse.sys.pojo.param.UserLoginInfoParam;
import com.example.warehouse.sys.pojo.param.UserUpdateParam;
import com.example.warehouse.sys.pojo.vo.UploadResult;
import com.example.warehouse.sys.pojo.vo.*;
import com.example.warehouse.sys.service.IUserService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Slf4j
@RestController
@RequestMapping("/sys/user")
@Api(tags = "1.1. 用户管理")
@Validated
public class UserController implements HttpConsts {
    @Autowired
    private IUserService iUserService;

    public UserController() {
        log.info("创建控制器对象:UserController");
    }

    @PostMapping("/login")
    @ApiOperation("用户登录")
    @ApiOperationSupport(order = 10)
    public JsonResult login(@Validated UserLoginInfoParam userLoginInfoParam,
                            @ApiIgnore HttpServletRequest request) {
        log.debug("开始处理【用户登录】的请求，参数：{}", userLoginInfoParam);
        String remoteAddr = request.getRemoteAddr();
        String userAgent = request.getHeader(HEADER_USER_AGENT);
        UserLoginResultVO userLoginResultVO = iUserService.login(userLoginInfoParam, remoteAddr, userAgent);
        return JsonResult.ok(userLoginResultVO);
    }

    @ApiOperation("创建用户")
    @ApiOperationSupport(order = 100)
    @PostMapping("insert/addUser")
    @PreAuthorize("hasAuthority('/sys/user/insert/addUser')")
    public JsonResult insert(@Valid AddNewUserParam addNewUserParam) {
        log.debug("开始处理 [用户注册] 的请求, 参数: {} ", addNewUserParam);
        iUserService.addNew(addNewUserParam);
        return JsonResult.ok();

    }

    @ApiOperation("删除用户")
    @ApiOperationSupport(order = 200)
    @PostMapping("delete/{id}/delUser")
    @PreAuthorize("hasAuthority('/sys/user/delete/delUser')")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "long")
    })
    public JsonResult deleteById(@PathVariable @Range(min = 1, message = "删除标签失败, 请提交合法参数!") Long id) {
        log.debug("开始处理 [删除用户] 的请求, 参数: {} ", id);
        iUserService.deleteById(id);
        return JsonResult.ok();

    }

    @ApiOperation("编辑")
    @ApiOperationSupport(order = 330)
    @PostMapping("update/upUser")
    @PreAuthorize("hasAuthority('/sys/user/update/upUser')")
    public JsonResult updateBySysUser(@Valid SysUserStandardParam sysUserStandardParam) {
        log.debug("开始处理 [修改用户参数] 的请求, 参数: {} ", sysUserStandardParam);
        iUserService.updateBySysUser(sysUserStandardParam);
        return JsonResult.ok();

    }

    @ApiOperation("重置密码")
    @ApiOperationSupport(order = 320)
    @PostMapping("update/{id}/upPassword")
    @PreAuthorize("hasAuthority('/sys/user/update/upPassword')")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "long")
    })
    public JsonResult updateByPassword(@PathVariable Long id) {
        log.debug("开始处理 [重置密码] 的请求, 参数: {} ", id);
        iUserService.updateByPassword(id);
        return JsonResult.ok();

    }

    @PostMapping("/{id:[0-9]+}/enable")
    @PreAuthorize("hasAuthority('/sys/user/updateEnable')")
    @ApiOperation("启用用户")
    @ApiOperationSupport(order = 310)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "long")
    })
    public JsonResult setEnable(@PathVariable Long id) {
        log.debug("开始处理【启用用户】的请求，参数：{}", id);
        iUserService.setEnable(id);
        return JsonResult.ok();
    }

    @PostMapping("/{id:[0-9]+}/disable")
    @PreAuthorize("hasAuthority('/sys/user/updateDisable')")
    @ApiOperation("禁用用户")
    @ApiOperationSupport(order = 311)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "long")
    })
    public JsonResult setDisable(@PathVariable Long id) {
        log.debug("开始处理【禁用用户】的请求，参数：{}", id);
        iUserService.setDisable(id);
        return JsonResult.ok();
    }

    @ApiOperation("用户列表")
    @ApiOperationSupport(order = 420)
    @GetMapping("/select/read")
    @PreAuthorize("hasAuthority('/sys/user/select/read')")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "页码", defaultValue = "1", dataType = "long")
    })
    public JsonResult list(Integer page){
        log.debug("开始处理【查询用户列表】的请求，页码：{}", page);
        Integer pageNum = page == null ? 1 : page;
        PageData<SysUserListItemVO> pageData = iUserService.list(pageNum);
        return JsonResult.ok(pageData);
    }


    @ApiOperation("用户列表导出")
    @ApiOperationSupport(order = 421)
    @GetMapping("/export")
    public void export(HttpServletResponse response)
            throws IOException {
        log.debug("处理{}",response);
        String fileName = "用户信息表";
        List<SysUser> list = iUserService.selectAll();
        ExcelUtil.download(response, fileName, SysUser.class,list
                );


    }

    @ApiOperation("用户信息查询")
    @ApiOperationSupport(order = 430)
    @GetMapping("/select/query-get")
    @PreAuthorize("hasAuthority('/sys/user/select/query-get')")
    @ApiImplicitParams({
            @ApiImplicitParam(name="deptName", value = "部门名称", dataType = "String"),
            @ApiImplicitParam(name="userName", value = "用户名称", dataType = "String"),
            @ApiImplicitParam(name="address", value = "用户地址", dataType = "String")
    })
    public JsonResult query(String deptName, String userName, String address){
        log.debug("开始处理【模糊查询用户信息】的请求，参数：{},{},{}",deptName,userName,address);
        List<UserCustomerStandardVO> userCustomerStandardVOS = iUserService.queryByKeyWord(deptName, userName, address);
        return JsonResult.ok(userCustomerStandardVOS);
    }
    @PostMapping("/logout")
    @ApiOperation("用户退出登录")
    @ApiOperationSupport(order = 11)
    public JsonResult logout(){
        log.debug("开始处理【用户登录】的请求，参数：{}");
        SecurityContextHolder.clearContext();
        return JsonResult.ok();
    }


    @GetMapping("/personal/infor")
    @ApiOperation("用户资料")
    @ApiOperationSupport(order = 12)
    public JsonResult infor(Long id){
        log.debug("开始处理【用户中心】的请求，参数：{}");

        UserPersonalVO userPersonalVO = iUserService.selectById(id);

        return JsonResult.ok(userPersonalVO);
    }


    @PostMapping("/personal/update/{id}/infor")
    @ApiOperation("用户修改资料")
    @ApiOperationSupport(order = 12)
    public JsonResult personal(@PathVariable Long id,@RequestBody UserUpdateParam userUpdateParam){
        log.debug("开始处理【用户修改资料】的请求，参数：{}");

        iUserService.updateByPersonal(id,userUpdateParam);

        
        return JsonResult.ok();
    }


    @PostMapping("/personal/update/{id}/password")
    @ApiOperation("用户修改密码")
    @ApiOperationSupport(order = 13)
    public JsonResult updatePassword(@PathVariable Long id,@RequestBody String password){
        log.debug("开始处理【用户修改密码】的请求，参数：id={},password={}",id,password);

        iUserService.updatePasswordById(id,password);
        return JsonResult.ok();
    }


    @Value("${warehouse.upload.host}")
    private String host;
    @Value("${warehouse.upload.base-dir-name}")
    private String baseDirName;
    @Value("${warehouse.upload.root-dir-name}")
    private String uploadRootDirName;

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd/");

    @Value("${warehouse.upload.article-image.max-size}")
    private Integer personalImageMaxSize;
    @Value("${warehouse.upload.article-image.types}")
    private List<String> personalImageValidTypes;
    private String personalImageDirName = "personal-image/";



    @PostMapping("/personal/upload")
    @ApiOperation("上传用户头像图片")
    @ApiOperationSupport(order = 12)
    public JsonResult personalUpload(@RequestParam("file") MultipartFile multipartFile) throws Throwable{
        if (multipartFile == null || multipartFile.isEmpty()) {
            String message = "上传文章图片失败，请选择您要上传的文件！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_UPLOAD_EMPTY, message);
        }

        long size = multipartFile.getSize();
        if (size > personalImageMaxSize * 1024 * 1024) {
            String message = "上传文章图片失败，不允许使用超过" + personalImageMaxSize + "MB的图片文件！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_UPLOAD_EXCEED_MAX_SIZE, message);
        }

        String contentType = multipartFile.getContentType();
        if (!personalImageValidTypes.contains(contentType)) {
            String message = "上传文章图片失败，请使用以下类型的图片文件：" + personalImageValidTypes;
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_UPLOAD_INVALID_TYPE, message);
        }

        String dirName = simpleDateFormat.format(new Date());
        File uploadBaseDir = new File(uploadRootDirName, baseDirName);
        File personalImageDir = new File(uploadBaseDir, personalImageDirName);
        File uploadDir = new File(personalImageDir, dirName);

        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }

        String newFileName = UUID.randomUUID().toString();
        String originalFilename = multipartFile.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        String newFullFileName = newFileName + suffix;
        File newFile = new File(uploadDir, newFullFileName);

        multipartFile.transferTo(newFile);

        String url = new StringBuilder()
                .append(host)
                .append(baseDirName)
                .append(personalImageDirName)
                .append(dirName)
                .append(newFullFileName)
                .toString();

        UploadResult uploadResult = new UploadResult();
        uploadResult.setUrl(url);
        uploadResult.setFileSize(size);
        uploadResult.setContentType(contentType);
        uploadResult.setFileName(newFullFileName);
        return JsonResult.ok(uploadResult);
    }

}
